from rest_framework import serializers
from . import models
from course.models import Course
from rest_framework.exceptions import ValidationError
from settings import dev


# 需要生成order对象，以及order_detail对象存入数据库。
# 生成支付宝url地址，通过context传导视图类，再response到前端。


class PaySerializer(serializers.ModelSerializer):
    # 要支持单购物和群购物(购物车)，前台要提交 课程主键(们)。
    # 继承的model没有此字段，所以要写一个去接收。
    courses = serializers.PrimaryKeyRelatedField(queryset=Course.objects.all(), write_only=True, many=True)

    class Meta:
        model = models.Order
        fields = ('subject', 'total_amount', 'pay_type', 'courses')
        extra_kwargs = {
            'total_amount': {
                'required': True
            },
            'pay_type': {
                'required': True
            },
        }

    # 订单总价校验
    def _check_total_amount(self, attrs):
        # 是一个queryset对象
        courses = attrs.get('courses')
        total_amount = attrs.get('total_amount')
        total_price = 0
        for course in courses:
            total_price += course.price
        if total_price != total_amount:
            raise ValidationError('总价不一致，错误！')
        return total_amount

    # 生成订单号
    def _get_out_trade_no(self):
        import uuid
        code = '%s' % uuid.uuid4()
        return code.replace('-', '')

    # 获取支付人
    def _get_user(self):
        return self.context.get('request').user

        # 获取支付链接

    def _get_pay_url(self, out_trade_no, total_amount, subject):
        from libs import iPay
        order_string = iPay.alipay.api_alipay_trade_page_pay(
            out_trade_no=out_trade_no,
            total_amount=float(total_amount),  # 只有生成支付宝链接时，不能用Decimal
            subject=subject,
            return_url=dev.RETURN_URL,
            notify_url=dev.NOTIFY_URL,

        )

        pay_url = iPay.gateway + '?' + order_string
        # 将支付链接存入，传递给views
        self.context['pay_url'] = pay_url

    def validate(self, attrs):
        # 1）订单总价校验
        total_amount = self._check_total_amount(attrs)
        # 2）生成订单号
        out_trade_no = self._get_out_trade_no()
        # 3）支付用户：request.user
        user = self._get_user()
        # 4）支付链接生成
        self._get_pay_url(out_trade_no, total_amount, attrs.get('subject'))
        # 5) attrs放入相应的值，准备入库。
        attrs['user'] = user
        attrs['out_trade_no'] = out_trade_no

        return attrs

    # 重写入库方法：完成订单与订单详情的同时入库

    def create(self, validated_data):
        # 订单表入库，不需要courses。
        courses = validated_data.pop('courses')

        order = models.Order.objects.create(**validated_data)

        # 订单详情表入库：只需要订单对象，课程对象(courses要拆成一个个course)
        for course in courses:
            models.OrderDetail.objects.create(order=order, course=course, price=course.price, real_price=course.price)

        return order
